#ifndef _BINARYMODULE_H_
#define _BINARYMODULE_H_

#include <QMap>
#include <QLibrary>

class CramBuilder;
struct _object;
typedef _object PyObject;
typedef ssize_t         Py_ssize_t;
typedef Py_ssize_t Py_hash_t;
struct _typeobject;
typedef _typeobject PyTypeObject;

typedef void (*PyInitFunc)();
typedef PyObject* (*PyWOArgFunc)();
typedef PyObject* (*PyWArgFunc)(PyObject*);
typedef int (*DictNextFunc)(PyObject*, Py_ssize_t*, PyObject**, PyObject**);
typedef PyObject* (*ModInfoFunc)(const char* name);
typedef char* (*PyBytes_AsStringFunc)(PyObject*);
typedef PyObject* (*PyUnicode_AsEncodedStringFunc)(PyObject*, const char*, const char*);
typedef PyObject* (*GetAttr)(PyObject*, const char*);
typedef int (*PT_Ready)(PyTypeObject*);
typedef PyObject* (*PyList_GetItemFunc)(PyObject*, Py_ssize_t);
typedef int (*PyObject_HasAttrStringFunc)(PyObject*, const char*);

class BinaryModule
{
public:
    BinaryModule();
    virtual ~BinaryModule();

    QStringList importPathes();
    QString import(const QString& importName);
private:
    QMap<QString, PyObject*> dir(PyObject* what);
    PyObject* importModule(const QString& modName);
    QString attrString(PyObject* obj, const QString& attrName);
    PyObject* attr(PyObject* obj, const QString& attrName);

    QString typeName(PyObject* o);
    QStringList getMro(PyObject* o);
    QString getDoc(PyObject* o);
    QStringList funcArgs(PyObject* o, const QString& funcName);
    QString funcReturn(PyObject* o, const QString& funcName);
    QString parseType(const QString& type);

    void free(const QMap<QString, PyObject*>&);
    void free(PyObject*);

    QString asString(PyObject* str);
    void processScope(PyObject* obj, CramBuilder* builder, bool onlyPublic = false);
private:
    QLibrary _lib;

    PyBytes_AsStringFunc _pyBytes_AsString;
    PyUnicode_AsEncodedStringFunc _pyUnicode_AsEncodedString;
    DictNextFunc _pyDictNext;
    ModInfoFunc _pyImportModule;
    PyWArgFunc _pyGetDict;
    GetAttr _pyAttrString;
    GetAttr _pyAttr;
    PyWArgFunc _pyDir;
    PyList_GetItemFunc _pyListGetItem;
    PyList_GetItemFunc _pySeqGetItem;
    PyObject_HasAttrStringFunc _pyHasAttr;
};

#endif
